#include "uart_forward.h"
#include "crc_chack.h"  
#include "crc_chack.h"  

extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart3;

static UartChannel_t uart1_channel;
static UartChannel_t uart3_channel;

static void process_channel_data(UartChannel_t *src_channel, UartChannel_t *dst_channel);
static bool check_packet_complete(UartChannel_t *channel);
static void send_packet(UartChannel_t *src_channel, UartChannel_t *dst_channel);

void uart_forward_init(void)
{
    uart1_channel.huart = &huart1;
    ring_buffer_init(&uart1_channel.rx_ring);
    uart1_channel.tx_busy = false;
    uart1_channel.state = FORWARD_STATE_IDLE;
    uart1_channel.rx_timeout_ms = 50; 
    uart1_channel.last_rx_tick = 0;
    uart1_channel.packets_received = 0;
    uart1_channel.packets_sent = 0;
    uart1_channel.crc_errors = 0;
    uart1_channel.buffer_overflows = 0;
    

    uart3_channel.huart = &huart3;
    ring_buffer_init(&uart3_channel.rx_ring);
    uart3_channel.tx_busy = false;
    uart3_channel.state = FORWARD_STATE_IDLE;
    uart3_channel.rx_timeout_ms = 50;  
    uart3_channel.last_rx_tick = 0;
    uart3_channel.packets_received = 0;
    uart3_channel.packets_sent = 0;
    uart3_channel.crc_errors = 0;
    uart3_channel.buffer_overflows = 0;
}

void uart_forward_start_receive(void)
{
    HAL_UART_Receive_IT(uart1_channel.huart, &uart1_channel.rx_byte, 1);
    uart1_channel.state = FORWARD_STATE_RECEIVING;
    
    HAL_UART_Receive_IT(uart3_channel.huart, &uart3_channel.rx_byte, 1);
    uart3_channel.state = FORWARD_STATE_RECEIVING;
}

void uart_forward_stop_receive(void)
{
    HAL_UART_AbortReceive_IT(uart1_channel.huart);
    HAL_UART_AbortReceive_IT(uart3_channel.huart);
    
    uart1_channel.state = FORWARD_STATE_IDLE;
    uart3_channel.state = FORWARD_STATE_IDLE;
}

void uart_forward_process(void)
{
    process_channel_data(&uart1_channel, &uart3_channel);
    
    process_channel_data(&uart3_channel, &uart1_channel);
    
    uint32_t current_tick = HAL_GetTick();
    
    if (uart1_channel.state == FORWARD_STATE_RECEIVING && 
        ring_buffer_available(&uart1_channel.rx_ring) > 0) {
        if ((current_tick - uart1_channel.last_rx_tick) > uart1_channel.rx_timeout_ms) {
            ring_buffer_clear(&uart1_channel.rx_ring);
        }
    }
    
    if (uart3_channel.state == FORWARD_STATE_RECEIVING && 
        ring_buffer_available(&uart3_channel.rx_ring) > 0) {
        if ((current_tick - uart3_channel.last_rx_tick) > uart3_channel.rx_timeout_ms) {
            ring_buffer_clear(&uart3_channel.rx_ring);
        }
    }
}

static void process_channel_data(UartChannel_t *src_channel, UartChannel_t *dst_channel)
{
    if (check_packet_complete(src_channel)) {
        if (!dst_channel->tx_busy) {
            send_packet(src_channel, dst_channel);
        }
    }
}

static bool check_packet_complete(UartChannel_t *channel)
{
    return (ring_buffer_available(&channel->rx_ring) >= PACKET_DATA_SIZE);
}

static void send_packet(UartChannel_t *src_channel, UartChannel_t *dst_channel)
{
    uint8_t packet_data[PACKET_DATA_SIZE];
    
    if (ring_buffer_pop_array(&src_channel->rx_ring, packet_data, PACKET_DATA_SIZE)) {
        for (int i = 0; i < PACKET_DATA_SIZE; i++) {
            dst_channel->tx_buffer[i] = packet_data[i];
        }
        
        uint8_t crc = crc8_maxim(dst_channel->tx_buffer, PACKET_DATA_SIZE);
        dst_channel->tx_buffer[PACKET_DATA_SIZE] = crc;
        
        dst_channel->tx_busy = true;
        dst_channel->state = FORWARD_STATE_SENDING;
        
        HAL_StatusTypeDef status = HAL_UART_Transmit_IT(dst_channel->huart, 
                                                        dst_channel->tx_buffer, 
                                                        PACKET_TOTAL_SIZE);
        
        if (status == HAL_OK) {
            src_channel->packets_received++;
            dst_channel->packets_sent++;
        } else {
            dst_channel->tx_busy = false;
            dst_channel->state = FORWARD_STATE_IDLE;
        }
    }
}

void uart_forward_rx_callback(UART_HandleTypeDef *huart)
{
    UartChannel_t *channel = NULL;
    
    if (huart == &huart1) {
        channel = &uart1_channel;
    } else if (huart == &huart3) {
        channel = &uart3_channel;
    } else {
        return;
    }
    
    if (!ring_buffer_push(&channel->rx_ring, channel->rx_byte)) {
        channel->buffer_overflows++;
    }
    
    channel->last_rx_tick = HAL_GetTick();
    
    HAL_UART_Receive_IT(channel->huart, &channel->rx_byte, 1);
}

void uart_forward_tx_callback(UART_HandleTypeDef *huart)
{
    UartChannel_t *channel = NULL;
    
    if (huart == &huart1) {
        channel = &uart1_channel;
    } else if (huart == &huart3) {
        channel = &uart3_channel;
    } else {
        return;
    }
    
    channel->tx_busy = false;
    channel->state = FORWARD_STATE_IDLE;
}

void uart_forward_error_callback(UART_HandleTypeDef *huart)
{
    UartChannel_t *channel = NULL;
    
    if (huart == &huart1) {
        channel = &uart1_channel;
    } else if (huart == &huart3) {
        channel = &uart3_channel;
    } else {
        return;
    }
    
    __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_ORE | UART_FLAG_NE | UART_FLAG_FE | UART_FLAG_PE);
    
    HAL_UART_Receive_IT(channel->huart, &channel->rx_byte, 1);
}

void uart_forward_get_stats(uint32_t *uart1_rx, uint32_t *uart1_tx, 
                           uint32_t *uart3_rx, uint32_t *uart3_tx)
{
    if (uart1_rx) *uart1_rx = uart1_channel.packets_received;
    if (uart1_tx) *uart1_tx = uart1_channel.packets_sent;
    if (uart3_rx) *uart3_rx = uart3_channel.packets_received;
    if (uart3_tx) *uart3_tx = uart3_channel.packets_sent;
}

void uart_forward_clear_errors(void)
{
    uart1_channel.crc_errors = 0;
    uart1_channel.buffer_overflows = 0;
    uart3_channel.crc_errors = 0;
    uart3_channel.buffer_overflows = 0;
}